import * as THREE from 'three';
import { Octree } from 'three/examples/jsm/math/Octree.js';
import { Capsule } from 'three/examples/jsm/math/Capsule.js';

// 常量
const GRAVITY = 20; // 重力参数
const JUMP_VELOCITY = 10; // 跳跃速度/高度
const playerRadius = 0.3; // 玩家胶囊体的半径
const playerHeight = 1.6; // 玩家高度

export default class CollideControls2 {
  // 主属性
  enabled = true; // 是否启用
  // 关联对象
  camera: THREE.PerspectiveCamera;
  dom: HTMLElement;
  worldOctree = new Octree();
  playerCollider = new Capsule(
    new THREE.Vector3(0, playerRadius, 0),
    new THREE.Vector3(0, playerHeight - playerRadius, 0),
    playerRadius
  );
  playerVelocity = new THREE.Vector3();
  playerOnFloor = false;

  constructor(camera: THREE.PerspectiveCamera, dom: HTMLElement) {
    this.camera = camera;
    this.camera.rotation.order = 'YXZ';
    this.dom = dom;
    // 鼠标
    this.onMouseDown = this._onMouseDown.bind(this);
    this.onMouseUp = this._onMouseUp.bind(this);
    this.onMouseMove = this._onMouseMove.bind(this);
    this.dom.addEventListener('mousedown', this.onMouseDown);
    this.dom.addEventListener('mouseup', this.onMouseUp);
    this.dom.addEventListener('mousemove', this.onMouseMove);
    // 键盘
    this.onKeyDown = this._onKeyDown.bind(this);
    this.onKeyUp = this._onKeyUp.bind(this);
    document.body.addEventListener('keydown', this.onKeyDown);
    document.body.addEventListener('keyup', this.onKeyUp);
  }

  // 烘焙八叉树
  bake(world: THREE.Object3D) {
    this.worldOctree.fromGraphNode(world);
  }

  // 玩家与世界碰撞
  playerCollisions() {
    const result = this.worldOctree.capsuleIntersect(this.playerCollider);
    this.playerOnFloor = false;
    if (result) {
      this.playerOnFloor = result.normal.y > 0;
      if (!this.playerOnFloor) {
        this.playerVelocity.addScaledVector(
          result.normal,
          -result.normal.dot(this.playerVelocity)
        );
      }
      this.playerCollider.translate(result.normal.multiplyScalar(result.depth));
    }
  }

  // 更新控制
  updateControls(deltaTime: number, keys: { [key: string]: boolean }) {
    
    const cameraDirection = new THREE.Vector3();
    const up = new THREE.Vector3(0, 1, 0);
    const cameraRight = new THREE.Vector3();

    // 更新前和右向量
    cameraDirection.set(0, 0, -1);
    cameraDirection.applyQuaternion(this.camera.quaternion).normalize();
    cameraRight.crossVectors(cameraDirection, up).normalize();

    const speedDelta = deltaTime * (this.playerOnFloor ? 25 : 8);
    // 前后左右
    if (this.pressedKeyMap['w']) {
      this.playerVelocity.add(cameraDirection.multiplyScalar(speedDelta));
    }
    if (this.pressedKeyMap['s']) {
      this.playerVelocity.add(cameraDirection.multiplyScalar(-speedDelta));
    }
    if (this.pressedKeyMap['a']) {
      this.playerVelocity.add(cameraRight.multiplyScalar(-speedDelta));
    }
    if (this.pressedKeyMap['d']) {
      this.playerVelocity.add(cameraRight.multiplyScalar(speedDelta));
    }
  }

  // 更新玩家
  updatePlayer(deltaTime: number) {
    let damping = Math.exp(-4 * deltaTime) - 1;
    if (!this.playerOnFloor) {
      this.playerVelocity.y -= GRAVITY * deltaTime;
      damping *= 0.1;
    }
    this.playerVelocity.addScaledVector(this.playerVelocity, damping);

    const deltaPosition = this.playerVelocity.clone().multiplyScalar(deltaTime);
    this.playerCollider.translate(deltaPosition);
    this.playerCollisions();
    const eyePos = new THREE.Vector3();
    eyePos.addVectors(
      this.playerCollider.end,
      new THREE.Vector3(0, playerRadius - 0.1, 0)
    ); // 调整眼睛位置
    this.camera.position.copy(eyePos);
  }

  // 鼠标
  isMouseLeft = false;
  onMouseDown: (e: MouseEvent) => void;
  onMouseUp: (e: MouseEvent) => void;
  onMouseMove: (e: MouseEvent) => void;
  _onMouseDown(e: MouseEvent) {
    if (!this.enabled) return;

    // console.log('[TourControls] onMouseDown')
    if (e.buttons == 1) this.isMouseLeft = true;
  }
  _onMouseUp(e: MouseEvent) {
    if (!this.enabled) return;

    // console.log('[TourControls] onMouseUp')
    this.isMouseLeft = false;
  }
  _onMouseMove(e: MouseEvent) {
    if (!this.enabled) return;

    // console.log('[TourControls] onMouseMove', this.isMouseLeft)
    if (this.isMouseLeft) {
      // console.log('拖拽相机', e.movementX, e.movementY)
      this.camera.rotation.y += e.movementX / 600;
      this.camera.rotation.x += e.movementY / 600;
    }
  }

  // 键盘
  pressedKeyMap: { [key: string]: boolean } = {};
  onKeyDown: (e: KeyboardEvent) => void;
  onKeyUp: (e: KeyboardEvent) => void;
  _onKeyDown(e: KeyboardEvent) {
    if (!this.enabled) return;

    // console.log('[TourControls] onKeyDown', e.key)
    this.pressedKeyMap[e.key] = true;
  }
  _onKeyUp(e: KeyboardEvent) {
    if (!this.enabled) return;

    // console.log('[TourControls] onKeyUp', e.key)
    this.pressedKeyMap[e.key] = false;
  }

  // 更新
  update(keys: { [key: string]: boolean }) {
    const deltaTime = 0.1; // 设置一个固定的 deltaTime，或者从外部传入
    this.updateControls(deltaTime, keys);
    this.updatePlayer(deltaTime);
  }
}
